package com.tracbds.core.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.tracbds.core.bean.VehicleLocation;

import java.util.Calendar;

/**
 * Redis消息服务类，支持List和Pub/Sub两种方式
 * @author lingx.com
 */
@Component
public class RedisMessageService {
    
    private static final Logger logger = LoggerFactory.getLogger(RedisMessageService.class);
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    
    @Value("${tracbds.redis.message.type:list}")
    private String messageType; // list 或 pubsub
    
    @Value("${tracbds.redis.message.channel:vehicle_location_data}")
    private String messageChannel;
    
    @Value("${tracbds.redis.message.queue:vehicle_location_data}")
    private String messageQueue;
    
    /**
     * 推送车辆定位数据
     * @param vehicleLocation 车辆定位数据
     */
    public void pushVehicleLocationData(VehicleLocation vehicleLocation) {
        if (vehicleLocation == null) {
            logger.warn("车辆定位数据为空，跳过推送");
            return;
        }
        
        try {
            String jsonData = JSON.toJSONString(vehicleLocation);
            
            if ("pubsub".equalsIgnoreCase(messageType)) {
                pushViaPubSub(jsonData);
            } else {
                pushViaList(jsonData);
            }
            
            logger.debug("推送车辆定位数据成功，方式: {}, 数据: {}", messageType, jsonData);
        } catch (Exception e) {
            logger.error("推送车辆定位数据失败: {}", e.getMessage(), e);
        }
    }
    
    /**
     * 推送车辆定位数据（使用Map数据）
     * @param locationData 定位数据Map
     */
    public void pushVehicleLocationDataFromMap(java.util.Map<String, Object> locationData) {
        try {
            // 从Map数据构建VehicleLocation对象
            VehicleLocation vehicleLocation = buildVehicleLocationFromMap(locationData);
            if (vehicleLocation != null) {
                pushVehicleLocationData(vehicleLocation);
            }
        } catch (Exception e) {
            logger.error("从Map数据推送车辆定位数据失败: {}", e.getMessage(), e);
        }
    }
    
    /**
     * 通过List方式推送消息
     * @param jsonData JSON数据
     */
    private void pushViaList(String jsonData) {
        redisTemplate.opsForList().rightPush(messageQueue, jsonData);
        logger.debug("通过List方式推送消息到队列: {}", messageQueue);
    }
    
    /**
     * 通过Pub/Sub方式推送消息
     * @param jsonData JSON数据
     */
    private void pushViaPubSub(String jsonData) {
        stringRedisTemplate.convertAndSend(messageChannel, jsonData);
        logger.debug("通过Pub/Sub方式推送消息到频道: {}", messageChannel);
    }
    
    /**
     * 从Map数据构建VehicleLocation对象
     * @param locationData 定位数据Map
     * @return VehicleLocation对象
     */
    private VehicleLocation buildVehicleLocationFromMap(java.util.Map<String, Object> locationData) {
        try {
            String vehicleId = (String) locationData.get("tid");
            if (vehicleId == null) {
                logger.warn("车辆ID为空，跳过推送");
                return null;
            }
            
            Double latitude = (Double) locationData.get("lat");
            Double longitude = (Double) locationData.get("lng");
            String gpstime = (String) locationData.get("gpstime");
            Float speedFloat = (Float) locationData.get("speed");
            Integer direction = (Integer) locationData.get("direction");
            
            // 转换速度从Float到Integer
            Integer speed = speedFloat != null ? speedFloat.intValue() : 0;
            
            // 解析GPS时间
            java.util.Date uploadTime = null;
            if (gpstime != null && gpstime.length() >= 14) {
                try {
                    java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyyMMddHHmmss");
                    uploadTime = sdf.parse(gpstime);
                } catch (Exception e) {
                    logger.warn("解析GPS时间失败: {}", gpstime);
                    uploadTime = new java.util.Date();
                }
            } else {
                uploadTime = new java.util.Date();
            }
            
            return new VehicleLocation(vehicleId, latitude, longitude, uploadTime, speed, direction);
        } catch (Exception e) {
            logger.error("构建VehicleLocation对象失败: {}", e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 获取Redis中指定键的值
     * @param key Redis键
     * @return 键对应的值，如果不存在返回null
     */
    public String getRedisValue(String key) {
        try {
            return redisTemplate.opsForValue().get(key);
        } catch (Exception e) {
            logger.error("获取Redis键值失败，key: {}, 错误: {}", key, e.getMessage());
            return null;
        }
    }
    
    /**
     * 从Redis Hash中获取指定trip_id的departure_time
     * @param tid GPS设备ID
     * @param tripId 行程ID
     * @return departure_time，如果不存在返回null
     */
    public String getDepartureTime(String tid, String tripId) {
        try {
            String key = String.format("tid:%s", tid);
            Object value = redisTemplate.opsForHash().get(key, tripId);
            if (value == null) {
                return null;
            }
            
            String departureTime = value.toString();
            // 清理多余的双引号，例如：""18:00"" -> 18:00
            if (departureTime != null) {
                departureTime = departureTime.replaceAll("^\"+|\"$", "").trim();
            }
            
            return departureTime;
        } catch (Exception e) {
            logger.error("获取departure_time失败，tid: {}, tripId: {}, 错误: {}", tid, tripId, e.getMessage());
            return null;
        }
    }
    
    /**
     * 获取Redis Hash中的所有trip_id
     * @param tid GPS设备ID
     * @return trip_id列表
     */
    public java.util.Set<Object> getAllTripIds(String tid) {
        try {
            String key = String.format("tid:%s", tid);
            return redisTemplate.opsForHash().keys(key);
        } catch (Exception e) {
            logger.error("获取trip_id列表失败，tid: {}, 错误: {}", tid, e.getMessage());
            return new java.util.HashSet<>();
        }
    }
    
    /**
     * 检查是否可以推送数据（基于时间条件）
     * @param tid GPS设备ID
     * @param tripId 行程ID
     * @return true表示可以推送，false表示不可以推送
     */
    public boolean canPushData(String tid, String tripId) {
        try {
            String departureTime = getDepartureTime(tid, tripId);
            
            if (departureTime == null || departureTime.trim().isEmpty()) {
                logger.debug("Redis Hash中tid: {}, tripId: {} 的departure_time不存在或为空，停止推送数据", tid, tripId);
                return false;
            }
            
            // 解析时间格式 HH:MM
            if (!departureTime.matches("\\d{2}:\\d{2}")) {
                logger.warn("tid: {}, tripId: {} 的departure_time格式不正确: {}，期望格式为MM:SS", tid, tripId, departureTime);
                return false;
            }
            
            String[] timeParts = departureTime.split(":");
            int hours = Integer.parseInt(timeParts[0]);
            int minutes = Integer.parseInt(timeParts[1]);
            
            // 获取当前时间的分钟和秒
            java.util.Calendar now = java.util.Calendar.getInstance();
            int currentMinutes = now.get(java.util.Calendar.MINUTE);
            int currentHours = now.get(Calendar.HOUR_OF_DAY);
            
            // 计算目标时间的总秒数
            int targetTotalSeconds = hours * 60 *60 + minutes * 60;
            // 计算当前时间的总秒数
            int currentTotalSeconds = currentHours * 60 * 60 + currentMinutes * 60;
            
            // 计算目标时间前10分钟的总秒数
            int tenMinutesBeforeTarget = targetTotalSeconds - 10 * 60;
            if (tenMinutesBeforeTarget < 0) {
                tenMinutesBeforeTarget += 60 * 60; // 如果小于0，加上一小时
            }
            
            // 判断当前时间是否在目标时间前10分钟内
            boolean canPush;
            canPush = currentTotalSeconds >= tenMinutesBeforeTarget;

            
            logger.debug("时间检查 - tid: {}, tripId: {}, 目标时间: {}, 当前时间: {}:{:02d}, 可推送: {}", 
                        tid, tripId, departureTime, currentHours,currentMinutes, canPush);
            
            return canPush;
            
        } catch (Exception e) {
            logger.error("检查推送条件时发生错误，tid: {}, tripId: {}, 错误: {}", tid, tripId, e.getMessage(), e);
            return false;
        }
    }
    
    /**
     * 检查是否可以推送数据（自动检查所有trip_id）
     * @param tid GPS设备ID
     * @return true表示至少有一个trip_id可以推送，false表示都不可以推送
     */
    public boolean canPushData(String tid) {
        try {
            java.util.Set<Object> tripIds = getAllTripIds(tid);
            
            if (tripIds.isEmpty()) {
                logger.debug("GPS设备 {} 没有任何trip_id，停止推送数据", tid);
                return false;
            }
            
            // 检查是否有任何一个trip_id满足推送条件
            for (Object tripIdObj : tripIds) {
                String tripId = tripIdObj.toString();
                if (canPushData(tid, tripId)) {
                    logger.debug("GPS设备 {} 的trip_id {} 满足推送条件", tid, tripId);
                    return true;
                }
            }
            
            logger.debug("GPS设备 {} 的所有trip_id都不满足推送条件", tid);
            return false;
            
        } catch (Exception e) {
            logger.error("检查推送条件时发生错误，tid: {}, 错误: {}", tid, e.getMessage(), e);
            return false;
        }
    }
    
    /**
     * 获取当前消息类型
     * @return 消息类型
     */
    public String getMessageType() {
        return messageType;
    }
    
    /**
     * 获取消息频道/队列名称
     * @return 频道/队列名称
     */
    public String getMessageChannel() {
        return "pubsub".equalsIgnoreCase(messageType) ? messageChannel : messageQueue;
    }
}